using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Reflection;
using System.Data;

namespace Adoor.Relational
{
	/// <summary>
	/// Summary description for EntityDataTable.
	/// </summary>
	public class EntityDataTable : DataTable
	{
		internal EntityDataTable() : base()
		{
			this.InitClass();
		}
            
		internal EntityDataTable(DataTable table) : 
			base(table.TableName) 
		{
			if ((table.CaseSensitive != table.DataSet.CaseSensitive)) 
			{
				this.CaseSensitive = table.CaseSensitive;
			}
			if ((table.Locale.ToString() != table.DataSet.Locale.ToString())) 
			{
				this.Locale = table.Locale;
			}
			if ((table.Namespace != table.DataSet.Namespace)) 
			{
				this.Namespace = table.Namespace;
			}
			this.Prefix = table.Prefix;
			this.MinimumCapacity = table.MinimumCapacity;
			this.DisplayExpression = table.DisplayExpression;
		}
            
		public EntityRow this[int index] 
		{
			get 
			{
				return ((EntityRow)(this.Rows[index]));
			}
		}            
            
		public System.Collections.IEnumerator GetEnumerator() 
		{
			return this.Rows.GetEnumerator();
		}
            
		public override DataTable Clone() 
		{
			EntityDataTable cln = ((EntityDataTable)(base.Clone()));
			cln.InitVars();
			return cln;
		}
            
		protected override DataTable CreateInstance() 
		{			
			return new EntityDataTable();
		}
            
		internal void InitVars() 
		{
              
		}
            
		private void InitClass() 
		{
			DataColumnCollection col = Columns;
			FieldInfo fi = typeof(DataColumnCollection).GetField("columnFromName", BindingFlags.NonPublic | BindingFlags.Instance);
			System.Collections.IDictionary oldValue = fi.GetValue(col) as System.Collections.IDictionary;
			fi.SetValue(col, CollectionsUtil.CreateCaseInsensitiveHashtable(oldValue));     
		}
            
            
		protected override DataRow NewRowFromBuilder(DataRowBuilder builder) 
		{
			return new EntityRow(builder);
		}
            
		protected override System.Type GetRowType() 
		{
			return typeof(EntityRow);
		}		
	}

	public class EntityRow : DataRow 
	{
            
		private EntityDataTable tableEntity;
            
		internal EntityRow(DataRowBuilder rb) : 
			base(rb) 
		{
			this.tableEntity = ((EntityDataTable)(this.Table));			
		}		
		
		private DataRow preloadingState = null;

		public void SetExtendedProperty(string name, int value)
		{
			DataRow lr = linkedRow;
			if(!lr.Table.Columns.Contains(name))
			{
				DataColumn dc = lr.Table.Columns.Add(name, typeof(int));
				dc.DefaultValue = 0;
				lr[name] = 0;
			}
			lr[name] = value;
			lr.AcceptChanges();
		}

		public int GetExtendedProperty(string name)
		{
			DataRow lr = linkedRow;
			if(!lr.Table.Columns.Contains(name))
			{
				DataColumn dc = lr.Table.Columns.Add(name, typeof(int));
				dc.DefaultValue = 0;
				lr[name] = 0;
			}
			object o = lr[name];
			if(DBNull.Value.Equals(o))
				lr[name] = 0;
			lr.AcceptChanges();
			return (int) lr[name];
		}

		private DataRow linkedRow
		{
			get
			{ 
				if(preloadingState == null)
				{
					DataTable dt = tableEntity.DataSet.Tables[tableEntity.TableName + "pls"];
					if(dt == null)
					{
						DataColumn[] dcpks = new DataColumn[tableEntity.PrimaryKey.Length];
						dt = new DataTable(tableEntity.TableName + "pls");
						for(int i = 0; i < tableEntity.PrimaryKey.Length; i++)
						{
							DataColumn dc = tableEntity.PrimaryKey[i];
							DataColumn dcPk = dt.Columns.Add(dc.ColumnName, dc.DataType);
							dcpks[i] = dcPk;
						}
						dt.PrimaryKey = dcpks;
						tableEntity.DataSet.Tables.Add(dt);
					}
					object[] pk = new object[tableEntity.PrimaryKey.Length];
					for(int i = 0; i < tableEntity.PrimaryKey.Length; i++)
					{
						pk[i] = this[tableEntity.PrimaryKey[i]];
					}
					preloadingState = dt.Rows.Find(pk);
					if(preloadingState == null)
					{
						preloadingState = dt.NewRow();
						for(int i = 0; i < tableEntity.PrimaryKey.Length; i++)
						{
							DataColumn dc = tableEntity.PrimaryKey[i];
							preloadingState[dc.ColumnName] = pk[i];							
						}
						dt.Rows.Add(preloadingState);
					}
				}
				preloadingState.AcceptChanges();
				return preloadingState; 
			}
		}		
	}
}
